package net.jalbum.filters;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;

public class MultipleResizableCirclePanel extends MultipleResizableObjectPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = -1065478330671173810L;
	protected MultipleResizableCircleControl multipleResizableCircleControl;
	protected ResizableCircle resizableCircle;
	protected boolean showRadius2 = true;
	protected double initalX = 0;
	protected double initalY = 0;
	protected double initalRadius1 = 0.2;
	protected double initalRadius2 = 0.1;

	public MultipleResizableCirclePanel() {
		this.name = "MultipleResizableCirclePanel";
		this.author = "David Fichtmueller";
		this.version = "1.0";
		this.description = "This is just for inheriting for other filters. This is not applieable.";
		this.prescale = true;
		this.postscale = false;

		this.resizableCircle = new ResizableCircle();

		this.resizableCircle.setName(this.namePrefix + this.counter);
		this.resizableCircle.setParentPanel(this);
		this.resizableCircle.setShowRadius2(this.showRadius2);
		this.resizableCircle.setX1(this.initalX);
		this.resizableCircle.setY1(this.initalY);
		this.resizableCircle.setRadius(this.initalRadius1);
		this.resizableCircle.setRadius2(this.initalRadius2);

		this.objectVector.clear();

		this.resizableObject = this.resizableCircle;
		this.hoveredOverObject = this.resizableObject;

		this.multipleResizableCircleControl = new MultipleResizableCircleControl(this);

	}

	@Override
	public JPanel getControls() {
		return this.multipleResizableCircleControl;
	}

	@Override
	public void addObject() {
		if (!this.resizableObject.isInitial()) {
			this.resizableObject.setState(ResizableObject.NOTHING);

			this.resizableCircle = new ResizableCircle(this.width, this.height);
			this.resizableCircle.setParentPanel(this);
			this.resizableCircle.setShowRadius2(this.showRadius2);
			// new circle is added on top of the others
			this.objectVector.add(0, this.resizableCircle);
			this.resizableCircle.setName(this.namePrefix + this.counter);
			this.resizableObject = this.resizableCircle;
			this.counter++;
		}
	}

	@Override
	protected void paintOutline(final Graphics g) {
		g.setColor(new Color(255, 255, 127, 127));
		this.resizableCircle = (ResizableCircle) this.resizableObject;
		// calculate the positions as pixel size
		final int intX1 = (int) (this.resizableCircle.getOutX1() * (this.width - 1));
		final int intY1 = (int) (this.resizableCircle.getOutY1() * (this.height - 1));
		final int intRadius1 = (int) (this.resizableCircle.getRadiusOut() * (this.width - 1));

		// draw outer circle as outline (the exact same way as the resizableCircle does to avoid rounding errors)
		g.drawOval(intX1 - intRadius1, intY1 - intRadius1, 2 * intRadius1, 2 * intRadius1);
	}

	public void updateCircle(final double x, final double y, final double radius, final double radius2) {
		// this method is called by the controller to pass new settings to the circle
		((ResizableCircle) (this.resizableObject)).update(x, y, radius, radius2);
		this.resizableObject.setInitial(false);
		this.renderPreview();
	}

	// adjust mouse Listeners to fit the coordinates of a resizable circle (x1 and y1 are the center and not the upper left corner)
	@Override
	public void mouseMoved(final MouseEvent event) {

		final int x = event.getX();
		final int y = event.getY();
		if (this.resizableObject != null) {
			if (this.resizableObject.isInitial()
					|| (x >= (this.resizableObject.getOutX1() - this.resizableObject.getObjectWidth() / 2) * (this.width - 1) - 5 && x <= (this.resizableObject.getOutX1() + this.resizableObject.getObjectWidth() / 2) * (this.width - 1) + 5
							&& y >= (this.resizableObject.getOutY1() + this.resizableObject.getObjectHeight() / 2) * (this.height - 1) - 5 && y <= (this.resizableObject.getOutY1() + this.resizableObject.getObjectHeight() / 2) * (this.height - 1) + 5)) {
				// pass the mouse position to the selected object, if it is initial or within its boundaries (plus 5 pixel of tolerance on each side)
				this.hoveredOverObject.setState(ResizableObject.NOTHING);
				this.hoveredOverObject = this.resizableObject;
				this.resizableObject.mouseMoved(event);
			} else {
				// check all the other objects, if it is not the currently selected one
				for (int i = 0; i < this.objectVector.size(); i++) {
					// go through all objects and check if clicked pixel belongs to one of them
					if (x >= (this.objectVector.get(i).getOutX1() - this.objectVector.get(i).getObjectWidth() / 2) * (this.width - 1) - 5 && x <= (this.objectVector.get(i).getOutX1() + this.objectVector.get(i).getObjectWidth() / 2) * (this.width - 1) + 5
							&& y >= (this.objectVector.get(i).getOutY1() - this.objectVector.get(i).getObjectHeight() / 2) * (this.height - 1) - 5 && y <= (this.objectVector.get(i).getOutY1() + this.objectVector.get(i).getObjectHeight()) * (this.height - 1) + 5) {
						// pass the mouse position to the first object it is over
						this.hoveredOverObject.setState(ResizableObject.NOTHING);
						this.hoveredOverObject = this.objectVector.get(i);
						this.hoveredOverObject.mouseMoved(event);
						return;
					}
				}
				// if the mouse is above none of the other objects, the call gets passed to the selected object
				this.hoveredOverObject.setState(ResizableObject.NOTHING);
				this.hoveredOverObject = this.resizableObject;
				this.resizableObject.mouseMoved(event);
			}
		}
	}

	@Override
	public void mousePressed(final MouseEvent event) {
		final int x = event.getX();
		final int y = event.getY();

		if (this.resizableObject != null) {
			if (this.resizableObject.isInitial()
					|| (x >= (this.resizableObject.getOutX1() - this.resizableObject.getObjectWidth() / 2) * (this.width - 1) - 5 && x <= (this.resizableObject.getOutX1() - this.resizableObject.getObjectWidth() / 2) * (this.width - 1) + 5
							&& y >= (this.resizableObject.getOutY1() + this.resizableObject.getObjectHeight() / 2) * (this.height - 1) - 5 && y <= (this.resizableObject.getOutY1() + this.resizableObject.getObjectHeight() / 2) * (this.height - 1) + 5)) {
				// pass the pressed mouse to the selected object, if it is initial or within its boundaries (plus 5 pixel of tolerance on each side)
				this.resizableObject.mousePressed(event);
			} else {
				// check all the other objects, if it is not the currently selected one
				for (int i = 0; i < this.objectVector.size(); i++) {
					// go through all objects and check if clicked pixel belongs to one of them
					if (x >= (this.objectVector.get(i).getOutX1() - this.objectVector.get(i).getObjectWidth() / 2) * (this.width - 1) - 5 && x <= (this.objectVector.get(i).getOutX1() + this.objectVector.get(i).getObjectWidth() / 2) * (this.width - 1) + 5
							&& y >= (this.objectVector.get(i).getOutY1() - this.objectVector.get(i).getObjectHeight() / 2) * (this.height - 1) - 5 && y <= (this.objectVector.get(i).getOutY1() + this.objectVector.get(i).getObjectHeight()) * (this.height - 1) + 5) {
						// select the first object within whose area the pixel is as the new current object;
						this.selectObject(i);
						this.resizableObject.mousePressed(event);
						return;
					}
				}
				// if none of the other objects is responsible for the clicked pixel, either a new Object is created or the call is passed to the already selected object
				if (this.emptyClickCreatesNewObject) {
					this.addObject();
					// setting the current position to the new object
					this.mousePressed(event);
					this.multipleResizableObjectControl.checkButtons();
					this.renderPreview();
				} else {
					// the call gets passed to the selected object
					this.resizableObject.mousePressed(event);
				}
			}
		}
	}

	@Override
	public void dispose() {
		super.dispose();
		this.resizableCircle = null;
	}

	public ResizableCircle getResizableCircle() {
		return (ResizableCircle) (this.resizableObject);
	}

	public boolean isShowRadius2() {
		return this.showRadius2;
	}

	public void setShowRadius2(final boolean showRadius2) {
		this.showRadius2 = showRadius2;
	}

	public double getInitalX() {
		return this.initalX;
	}

	public void setInitalX(final double initalX) {
		this.initalX = initalX;
	}

	public double getInitalY() {
		return this.initalY;
	}

	public void setInitalY(final double initalY) {
		this.initalY = initalY;
	}

	public double getInitalRadius1() {
		return this.initalRadius1;
	}

	public void setInitalRadius1(final double initalRadius1) {
		this.initalRadius1 = initalRadius1;
	}

	public double getInitalRadius2() {
		return this.initalRadius2;
	}

	public void setInitalRadius2(final double initalRadius2) {
		this.initalRadius2 = initalRadius2;
	}

	public MultipleResizableCircleControl getMultipleResizableCircleControl() {
		return this.multipleResizableCircleControl;
	}

	public void setResizableCircle(final ResizableCircle resizableCircle) {
		this.resizableCircle = resizableCircle;
	}
}
